using System;
using System.Collections.Generic;
using CLELCore.Assembly.Descriptors.ClassDescriptors;
using CLELCore.Assembly.BlobStreams;

namespace CLELCore.Assembly.BlobStreams.BlobInfo
{
	public class MethodLocalsBlobInfo
	{
		private List<ClassDescriptor> _locals;

		public List<ClassDescriptor> Locals
		{
			get
			{
				return _locals;
			}
			set
			{
				_locals = value;
			}
		}

		public MethodLocalsBlobInfo(byte [] blob,CLELAssembly assembly)
		{
			_locals = new List<ClassDescriptor>();
			if(blob != null)
			{
				int start_offset = 0;
				Blob.DecompressBlobValue(blob,ref start_offset); //skip flags and size
				if(blob[start_offset] != BlobType.LOCAL_SIG_BLOB_TYPE) //check for locals magic number
					throw new ArgumentException("Blob value does not contain locals");
				start_offset++;
				uint num_params = (uint)Blob.DecompressBlobValue(blob,ref start_offset); //get number of parameters
				uint i;
				ClassDescriptor cd;
				for(i = 0;i < num_params;i++) //get each parameter
				{
					cd = ClassDescriptor.ParseMethodLocalTypeFromBlob(assembly,blob,ref start_offset);
					_locals.Add(cd);
				}
			}
		}

		public byte [] MethodLocalsToBytes()
		{
			int num_locals = _locals.Count;
			byte [][] locals = new byte[num_locals][];
			int i;
			int count = 0;
			byte [] temp;
			for(i = 0;i < num_locals;i++)
			{
				temp = _locals[i].ToBytes();
				count += temp.Length;
				locals[i] = temp;
			}

			//method locals flag
			count++;
			//add room to hold params count
			byte [] params_count = Blob.CompressBlobValue(num_locals);
			count += params_count.Length;
			byte [] count_bytes = Blob.CompressBlobValue(count);
			count += count_bytes.Length;		

			byte [] ret = new byte[count];
			int next = 0;
			//add flags and count
			for(i = 0;i < count_bytes.Length;i++,next++)
				ret[next] = count_bytes[i];
			//add method locals flag
			ret[next] = BlobType.LOCAL_SIG_BLOB_TYPE;
			next++;
			//add params count
			for(i = 0;i < params_count.Length;i++,next++)
				ret[next] = params_count[i];
			//add each type
			int j;
			for(i = 0;i < locals.Length;i++)
			{
				temp = locals[i];
				for(j = 0;j < temp.Length;j++,next++)
					ret[next] = temp[j];
			}
			
			return ret;
		}
	}
}
